(* ===================================================================== *)
(** bop2tools : outils pour les applications de traduction d'une net-list 
    .bop vers un autre format : utilisee dans bop2xml
    @author Mathieu Barbin
    @version 1.0.* *)
(* ===================================================================== *)

(* ===================================================================== *)
(** Affichage : centrer des chaines de caracteres 
    @param s une chaine courte à centrer
    @param into une chaine longue 
    @return res une chaine fraiche égale à into sauf qu'on a remplacé 
    le centre d'into par s *)
(* ===================================================================== *)
let center s into =
  let leninto = String.length into
  and lens = String.length s in
  if lens >= leninto
  then String.sub s 0 leninto
  else 
    begin
      let reste = (leninto - lens) / 2 in
      let out = String.copy into in
      String.blit s 0 out reste lens;
      out
    end;;
(* =================================================================== *)

type execution = 
    {
      source : string;
      destination : t_destination
    }
and t_destination = DestStdout | DestFile of string

(** Exeption levee quand la ligne de commande est incoherente *)
exception Arguments_Invalides

(* ===================================================================== *)
(** Trouver l'indice d'un element dans un tableau avec une fonction de comparaison *)
(* ===================================================================== *)
let find_in_array cmp e t =
  let len = Array.length t in
  let rec aux i = 
    if i >= len then None
    else 
      if cmp e (Array.unsafe_get t i)
      then Some i
      else aux (succ i)
  in aux 0
(* ===================================================================== *)

(* ===================================================================== *)
(** Déduire le mode d'execution a partir du sys_argv *)
(* ===================================================================== *)
let execution_of_argv sys_argv =
  let len = Array.length sys_argv in
  match len with
  | 2 -> { source = sys_argv.(1); destination = DestStdout }
  | 4 ->
      begin
	match (find_in_array (fun a b -> String.compare a b = 0) "-o" sys_argv) with
	| Some 1 -> { source = sys_argv.(3); destination = DestFile sys_argv.(2) }
	| Some 2 -> { source = sys_argv.(1); destination = DestFile sys_argv.(3) }
	| _ -> raise Arguments_Invalides
      end
  | _ -> raise Arguments_Invalides    
(* ===================================================================== *)

(* ===================================================================== *)
(** L'interface du module a ecrire pour implementer une nouvelle transcription *)
(* ===================================================================== *)
module type Transcriptor = 
  sig
    val init : (string -> unit) -> string -> unit
    val of_macros_declaration : (string -> unit) -> Inputtools.macro_define list -> unit
    val of_memories_declaration : (string -> unit) -> Inputtools.declaration_memoire list -> unit
    val of_fonctions_declaration : (string -> unit) -> Inputtools.declaration_generique_fonction list -> unit
  end
(* ===================================================================== *)

(* ===================================================================== *)
(** produire le code vhdl a l'aide d'une fonction prod a partir du resultat
    du parser sur un nom de fichier *)
(* ===================================================================== *)
module CodeProducer = functor (T:Transcriptor) -> 
  struct
    let of_bopfile prod bopfile =
      match Cdsmaker.net_list_of_file bopfile with
      | include_lib, macros_decl, mems_decl, bloc_ext_decl, fcts_decl, _ ->
          ignore include_lib;
	  T.init prod bopfile;
	  T.of_macros_declaration prod macros_decl;
	  T.of_memories_declaration prod mems_decl;
	  T.of_fonctions_declaration prod fcts_decl;
  end
(* ===================================================================== *)
